//
// Created by vivi on 10/12/2017.
//

#ifndef HAIRCORE_HAIRACCELERATEDSELLESIMULATOR_H
#define HAIRCORE_HAIRACCELERATEDSELLESIMULATOR_H

#include "HairSelleSimulator.h"
#include <Eigen/Eigen>

namespace XRwy {
	class HairAcceleratedSelleSimulatorStrandSolverContainer;
	class HairAcceleratedSelleSimulator;

	struct Band7Matrix3fGroup {
		Eigen::Matrix3f storage[7];

		inline Eigen::Matrix3f & operator[](const size_t & idx) { return storage[idx]; }
		inline const Eigen::Matrix3f & operator[](const size_t &idx) const { return storage[idx]; }
	};

	class HairAcceleratedSelleSimulatorStrandSolverContainer final {
	public:
		explicit HairAcceleratedSelleSimulatorStrandSolverContainer(StrandView & strand_view);

		inline void push_spring(const HairSelleSimulatorSpring & spring);

		const StrandView * strand_view_ptr;

		size_t n; //the particle size of this size
		std::list<const HairSelleSimulatorSpring *> spring_ptrs; //the mass spring that takes over in this strand
		std::vector<Band7Matrix3fGroup> A;
		std::vector<Eigen::Matrix3f> L3, L2, L1, L0, U0, U1, U2, L0i;
		std::vector<Eigen::Vector3f> b, y, x;
	};

	class HairAcceleratedSelleSimulator: public HairSelleSimulator {
		friend class HairAcceleratedSelleSimulatorStrandSolverContainer;
	public:
		HairAcceleratedSelleSimulator(const HairReader & reader, const HairSelleSimulatorConfiguration &conf);

		virtual ~HairAcceleratedSelleSimulator();

		virtual void strand_dynamic(const Eigen::Affine3f &, const float t);

	private:
		std::vector<HairAcceleratedSelleSimulatorStrandSolverContainer> solver_containers;
	};
}

#endif //HAIRCORE_HAIRACCELERATEDSELLESIMULATOR_H
